<?php
namespace Admin\Api;

use PhalApi\Api;
use PhalApi\Exception\BadRequestException;

/**
 * OAuth身份验证
 * @link https://bshaffer.github.io/oauth2-server-php-docs/cookbook/
 */
class OAuth extends Api {

    public function getRules() {
        $help = '
                <ul>
                    <li>code，表示Authorization Code，OAuth最常用的授权方式，用于第三方系统的用户请求访问受保护资源时。</li>
                    <!--<li>token，表示Implicit，隐式授权类型与授权代码授权类型类似，因为它用于代表另一个用户（即第三方）请求访问受保护的资源。</li>-->
                    <li>password，表示User Credentials，使用会员账户密码登录</li>
                    <li>client_credentials，表示Client Credentials，当客户端请求访问其控制下的受保护资源（即没有第三方）时，将使用客户端凭据授予类型。</li>
                    </ul>';

        return array(
            'userLogin' => array(
                'username' => array('name' => 'username', 'source' => 'POST', 'require' => true, 'desc' => '登录账号，使用POST方式传递'),
                'password' => array('name' => 'password', 'source' => 'POST', 'require' => true, 'desc' => '登录密码，使用POST方式传递'),
                'clientId' => array('name' => 'client_id', 'source' => 'POST', 'require' => true, 'desc' => '客户端ID'),
                'clientSecret' => array('name' => 'client_secret', 'source' => 'POST', 'require' => false, 'desc' => '客户端密钥'),
                //'grantType'  => array('name' => 'grant_type', 'default' => 'client_credentials', 'desc' => '授权方式，其中：'. $help),
            ),
            'tokenClient' => array(
                //'grantType'  => array('name' => 'grant_type', 'default' => 'client_credentials', 'desc' => '授权方式，其中：'. $help),
            ),
            'resource' => array(
                'accessToken'  => array('name' => 'access_token', 'require' => true, 'desc' => 'access_token'),
            ),
            'authorize' => array(
                'clientId' => array('name' => 'client_id', 'require' => true, 'desc' => '客户端ID'),
                //'clientSecret' => array('name' => 'client_secret', 'require' => true, 'desc' => '客户端密钥'),
                'grantType'  => array('name' => 'grant_type', 'default' => 'client_credentials', 'desc' => '授权方式'),
                'responseType' => array('name' => 'response_type', 'require' => true, 'default' => 'code', 'desc' => '返回方式，其中：code，返回token的json数据'),
                'state' => array('name' => 'state', 'require' => true, 'desc' => ''),
            ),
        );
    }

    /**
     * OAuth身份验证-生成Token
     * @desc 生成Token
     * @method POST
     * @return string access_token 
     * @return string token_type
     * @return string scope 没有时为null
     * @return int expires_in 单位：秒，多少时间内有效
     */
    public function userLogin() {
        $_GET['grant_type'] = $_POST['grant_type'] = 'password';
        $_GET['username'] = $_POST['username'] = $this->username;
        $_GET['password'] = $_POST['password'] = $this->password;
        $_GET['client_secret'] = $_POST['client_secret'] = $this->clientSecret;
        $_GET['client_id'] = $_POST['client_id'] = $this->clientId;

        $server = $this->getServer();

        // Handle a request for an OAuth2.0 Access Token and send the response to the client
        $res = $server->handleTokenRequest(\OAuth2\Request::createFromGlobals());
        //  Uncaught PDOException: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'phalapi_api.oauth_clients' doesn't exist in /home/apps/dogstar/api/src/oauth2-server-php/src/OAuth2/Storage/Pdo.php:95

        return $this->parseOAuthResponse($res);
    }

    //public function tokenClient() {
    //    $_POST['grant_type'] = $this->grantType;
    //    $_POST['client_secret'] = $this->clientSecret;
    //    $_POST['client_id'] = $this->clientId;
    //}

    /**
     * OAuth身份验证-生成Token
     * @desc 生成Token
     * @ignore
     * @method POST
     * @return string access_token 
     * @return string token_type
     * @return string scope 没有时为null
     * @return int expires_in 单位：秒，多少时间内有效
     */
    protected function token() {

        $server = $this->getServer();

        // Handle a request for an OAuth2.0 Access Token and send the response to the client
        $res = $server->handleTokenRequest(\OAuth2\Request::createFromGlobals());
        //  Uncaught PDOException: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'phalapi_api.oauth_clients' doesn't exist in /home/apps/dogstar/api/src/oauth2-server-php/src/OAuth2/Storage/Pdo.php:95

        return $this->parseOAuthResponse($res);
    }

    /**
     * OAuth身份验证-资源检测
     * @desc OAuth身份验证-资源检测
     *
     */
    public function resource() {
        $rs = array('err_code' => 0, 'err_msg' => '');
        $server = $this->getServer();

        // Handle a request to a resource and authenticate the access token
        if (!$server->verifyResourceRequest(\OAuth2\Request::createFromGlobals())) {
            return $this->parseOAuthResponse($server->getResponse());
        }

        return $rs;
    }

    /**
     * OAuth身份验证-登录
     */
    public function authorize() {
        $server = $this->getServer();

        $request = \OAuth2\Request::createFromGlobals();
        $response = new \OAuth2\Response();

        // validate the authorize request
        if (!$server->validateAuthorizeRequest($request, $response)) {
            return $this->parseOAuthResponse($response);
            //$response->send();
            //die;
        }
        // display an authorization form
        if (empty($_POST)) {
            exit('
                <form method="post">
                <label>Do You Authorize TestClient?</label><br />
                <input type="submit" name="authorized" value="yes">
                <input type="submit" name="authorized" value="no">
                </form>');
        }

        // print the authorization code if the user has authorized your client
        $is_authorized = ($_POST['authorized'] === 'yes');
        $server->handleAuthorizeRequest($request, $response, $is_authorized);
        if ($is_authorized) {
            // this is only here so that you get to see your code in the cURL request. Otherwise, we'd redirect back to the client
            $code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=')+5, 40);
            exit("SUCCESS! Authorization Code: $code");
        }
        $response->send();
    }

    protected function parseOAuthResponse($res) {
        $params = $res->getParameters();

        if (!empty($params['error'])) {
            throw new BadRequestException($params['error'] . '，' . $params['error_description']);
        }

        $rs = array('err_code' => 0, 'err_msg' => '');
        $rs = array_merge($rs, $params);

        if ($res->getStatusCode() == 200) {
        } else {
        }

        return $rs;
    }

    protected function getServer() {
        $oauth = \PhalApi\DI()->get('oatuh', 'App\\Common\\OauthServer');
        return $oauth->getServer();
    }
}
